import * as step from '@flow-step/step-toolkit'
import process from "process";

const FLOW_JOB_TOKEN: string = 'FLOW_JOB_TOKEN'

export class DockerRepositoryInfo {
    type: 'acr' | 'acree';
    region: string;
    instance?: string;

    constructor(type: 'acr' | 'acree', region: string, instance?: string) {
        this.type = type;
        this.region = region;
        this.instance = instance;
    }
}

export function parseDockerRepositoryInfo(dockerRepository: string): DockerRepositoryInfo {
    const acrRegex = /^registry(?:-vpc)?\.([^.]+)\.aliyuncs\.com$/;

    // 'crpi-3ixfhqbc23r7bca7.cn-hangzhou.personal.cr.aliyuncs.com'
    const acrRegexNew = /^crpi-[^.]+\.([^.]+)\.personal\.cr\.aliyuncs\.com$/;

    const acreeRegex = /^([^.]+)-registry(?:-vpc)?\.([^.]+)\.cr\.aliyuncs\.com$/;

    if (acrRegex.test(dockerRepository)) {
        const region = dockerRepository.match(acrRegex)?.[1];
        return new DockerRepositoryInfo('acr', region as string);
    } else if(acrRegexNew.test(dockerRepository)) {
        const region = dockerRepository.match(acrRegexNew)?.[1];
        return new DockerRepositoryInfo('acr', region as string);
    } else if (acreeRegex.test(dockerRepository)) {
        return new DockerRepositoryInfo('acree', dockerRepository.match(acreeRegex)?.[2] as string, dockerRepository.match(acreeRegex)?.[1]);
    } else {
        throw new Error(`Unknown repository type ${dockerRepository}`);
    }
}


export async function setup(dockerRepository: string) {
    step.info(`Going to execute docker login acr step.`)

    const serviceConnectionId = process.env["SERVICE_CONNECTION_ID"];
    if (serviceConnectionId == undefined) {
        throw new Error('missing SERVICE_CONNECTION_ID')
    }

    const flowJobToken: string | undefined =
        process.env[FLOW_JOB_TOKEN]

    if (flowJobToken == undefined) {
        throw new Error('missing FLOW_JOB_TOKEN')
    }

    let dockerUsername = ""
    let dockerPassword = ""

    const dockerRepositoryInfo = parseDockerRepositoryInfo(dockerRepository)
    if (dockerRepositoryInfo.type == 'acr') {
        const dockerACRPersonalCertificate = await step.certificate.getDockerAcrPersonalCertificate(flowJobToken, serviceConnectionId as string, dockerRepositoryInfo.region);
        if (dockerACRPersonalCertificate == undefined || dockerACRPersonalCertificate.username == undefined) {
            throw new Error(`get dockerACRPersonalCertificate but error: ${JSON.stringify(dockerACRPersonalCertificate)}`)
        }

        dockerUsername = dockerACRPersonalCertificate.username
        dockerPassword = dockerACRPersonalCertificate.password
    } else {
        const dockerACREECertificate = await step.certificate.getDockerAcrEnterpriseCertificate(flowJobToken, serviceConnectionId as string, dockerRepositoryInfo.region, dockerRepositoryInfo.instance as string);
        if (dockerACREECertificate == undefined || dockerACREECertificate.username == undefined) {
            throw new Error(`get dockerACREECertificate but error: ${JSON.stringify(dockerACREECertificate)}`)
        }

        dockerUsername = dockerACREECertificate.username
        dockerPassword = dockerACREECertificate.password
    }


    if (dockerUsername == undefined || dockerPassword == undefined) {
        throw new Error('missing docker username or password')
    }

    step.info(`docker login -u ${dockerUsername} -p **** ${dockerRepository}`)
    const resultCode = await step.exec.call('docker', ['login', '-u', dockerUsername, '-p', dockerPassword, dockerRepository], {
        listener: {
            stdoutLine: (line: string) => {
                step.info(line)
            },
            stderrLine: (line: string) => step.info(line),
        }
    })

    if (resultCode != 0) {
        throw new Error(`docker login -u ${dockerUsername} -p **** ${dockerRepository} but error`)
    }
}